package ace.cmp.spring.data.jdbc.querydsl.annotation.processor;

import com.google.common.base.CaseFormat;
import com.infobip.spring.data.jdbc.annotation.processor.CustomExtendedTypeFactory;
import com.querydsl.apt.Configuration;
import com.querydsl.codegen.EntityType;
import com.querydsl.codegen.QueryTypeFactory;
import com.querydsl.codegen.TypeMappings;
import java.lang.annotation.Annotation;
import java.util.Optional;
import java.util.Set;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.util.Elements;
import org.springframework.data.relational.core.mapping.Table;

/**
 * @author caspar
 * @date 2023/4/6 17:15
 */
public class AceCustomExtendedTypeFactory extends CustomExtendedTypeFactory {
  private final CaseFormat tableCaseFormat;
  private final Elements elements;

  public AceCustomExtendedTypeFactory(
      RoundEnvironment roundEnv,
      ProcessingEnvironment env,
      Set<Class<? extends Annotation>> annotations,
      TypeMappings typeMappings,
      QueryTypeFactory queryTypeFactory,
      Configuration configuration,
      Elements elements,
      CaseFormat tableCaseFormat) {
    super(
        roundEnv,
        env,
        annotations,
        typeMappings,
        queryTypeFactory,
        configuration,
        elements,
        tableCaseFormat);
    this.tableCaseFormat = tableCaseFormat;
    this.elements = elements;
  }

  @Override
  protected String getTableName(EntityType model) {
    var simpleName = model.getSimpleName();
    var className = model.getPackageName() + "." + simpleName;
    var tableName = CaseFormat.UPPER_CAMEL.to(tableCaseFormat, simpleName);
    String result =
        Optional.ofNullable(elements.getTypeElement(className).getAnnotation(Table.class))
            .map(this::getTableName)
            .orElse(null);
    if (result != null && result.length() > 0) {
      return result;
    }
    return tableName;
  }

  private String getTableName(Table table) {

    if (table.value().isEmpty()) {
      return table.name();
    }

    return table.value();
  }
}
